package com.mass.core.token;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.security.Key;
import java.util.Date;

import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;

import com.mass.core.framework.security.SecurityUser;

@Component
public class JwtComponent {
	
	@Autowired
	private Audience audience;
	
	@Autowired
    private UserDetailsService userDetailsService;
	
	@Autowired
	private HttpServletRequest request;
	
    /**
     * 解析jwt
     */
    public Claims parseJWT(String jsonWebToken){
        try
        {
            Claims claims = Jwts.parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(audience.getBase64Secret()))
                    .parseClaimsJws(jsonWebToken).getBody();
            return claims;
        }
        catch(Exception ex)
        {
            return null;
        }
    }
    /**
     * 构建jwt
     */
    public String createJWT(String name, String userId, String role)
    {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        //生成签名密钥
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(audience.getBase64Secret());
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
        //添加构成JWT的参数
        JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
                .claim("role", role)
                .claim("unique_name", name)
                .claim("userid", userId)
                .setIssuer(audience.getName())
                .setAudience(audience.getClientId())
                .signWith(signatureAlgorithm, signingKey);
        //添加Token过期时间
        //if (TTLMillis >= 0) {
            long expMillis = nowMillis + audience.getExpiresSecond()*1000;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp).setNotBefore(now);
        //}
        SecurityUser userDetails = new SecurityUser();
        userDetails.setUserName(name);
            //if (jwtTokenUtil.validateToken(authToken, userDetails)) {
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authentication);
            //}
        //生成JWT
        return builder.compact();
    }
    /**
     * 刷新令牌
     *
     * @param token 原令牌
     * @return 新令牌
     */
    public String refreshToken(String token) {
        String refreshedToken = null;
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        //生成签名密钥
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(audience.getBase64Secret());
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
        try {
        	Claims claims = Jwts.parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(audience.getBase64Secret()))
                    .parseClaimsJws(token).getBody();
        	long nowMillis = System.currentTimeMillis();
        	claims.setExpiration(new Date(nowMillis+audience.getExpiresSecond()*1000));
        	claims.setNotBefore(new Date(nowMillis));
        	JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT").setClaims(claims).signWith(signatureAlgorithm, signingKey);;
        	return builder.compact();
        } catch (Exception e) {
        	return refreshedToken;
        }
    }
}